/**
 * \file  xtc2pdb.cpp
 * \brief Tool for converting .xtc files to .pdb format.
 *
 * FDC: FuDePAN Distributed Clusterer
 * <http://fud.googlecode.com/>
 * Copyright (C) 2009 Guillermo Biset, FuDePAN
 *
 * This file is part of the FuD project.
 *
 * Contents:       Tool for converting .xtc file to gnuplot command file.
 *
 *
 * System:         FDC
 * Language:       C++
 *
 * Author:         Guillermo Biset
 * E-Mail:         billybiset AT gmail.com
 *
 * FDC is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FDC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with FuD.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>

extern "C"
{
    #include "xdrfile.h"
    #include "xdrfile_xtc.h"
}

#include "getopt_pp.h"

using namespace GetOpt;

void show_help()
{
    std::cout << "xtc2pbd generates a .pdb file from an .xtc one.\n"
        "\t Example: xtc2pdb -i input.xtc -o output.pdb\n\n"
        "Valid options are:\n"
        "\t-i --input                  Input .xtc file.\n"
        "\t-o --output                 Output .pdb file.\n"
        "\t-h --help                   Show this help and exits.\n\n"
    ;
}

void output_protein(std::ofstream& file, int atoms, size_t protein, const rvec* atoms_vector, size_t& t)
{
        file << "REMARK    GENERATED BY XTC2PDB\n"
             << "TITLE     t=0.000 t= " <<  t << ".00000\n"
             << "MODEL        " << protein << std::endl;

        t += 500;

        int triple(1);
        int atom(1);

        while (atom <= atoms)
        {
            file << "ATOM " << std::setw(6) << atom << "  N   ALA A " << std::setw(3) << triple << "    "
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][0] * 10
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][1] * 10
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][2] * 10 << "  1.00  0.00\n";

            ++atom;

            file << "ATOM " << std::setw(6) << atom << "  CA  ALA A " << std::setw(3) << triple << "    "
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][0] * 10
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][1] * 10
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][2] * 10 << "  1.00  0.00\n";

            ++atom;

            file << "ATOM " << std::setw(6) << atom << "  C   ALA A " << std::setw(3) << triple << "    "
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][0] * 10
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][1] * 10
                 << std::setw(8) << std::fixed <<  std::setprecision(3) << atoms_vector[atom-1][2] * 10 << "  1.00  0.00\n";

            ++atom;
            ++triple;
        }
        file << "TER\nENDMDL\n";
}

void output(XDRFILE* xdrfile, int atoms,const std::string& input, const std::string& output_file)
{
    std::ofstream file;
    file.open( output_file.c_str() );

    bool _finished_reading(false);

    int result;

    size_t t(0);
    size_t protein(0);

    while (!_finished_reading)
    {
        rvec   _atoms_vector[atoms];
        int    step;
        float  time;
        matrix box;
        float  prec;

        result = read_xtc(xdrfile,atoms,&step,&time,box,_atoms_vector,&prec);

        if (exdrENDOFFILE == result)
            _finished_reading = true;
        else if (exdrOK != result)
        {
            std::cerr << "ERROR: read_xtc " << result << std::endl;
            _finished_reading = true;
        }
        else
            output_protein(file, atoms, protein , _atoms_vector ,t);

        ++protein;
    }

    file.close();
    xdrfile_close(xdrfile);
}


int main(int argc, char *argv[])
{
    GetOpt_pp options(argc,argv);

    if (! (options >> OptionPresent('i',"input")) || ! (options >> OptionPresent('o',"output")) )
        show_help();
    else
    {
        std::string output_file;
        std::string input;

        size_t first(0);
        size_t total(0);

        options >> Option('i',"input",input) >> Option('o',"output",output_file)
                >> Option('f',"first",first) >> Option('t',"total",total);

        int atoms;
        int result;

        // You can't always get what you want...
        std::string str(input);
        char *fname = new char[str.size() + 1];
        strcpy(fname,str.c_str());
        // ...(RS)

        result = read_xtc_natoms(fname,&atoms);

        if (exdrOK != result)
            std::cerr <<"Error initializing database. Wrong filename?\n";

        XDRFILE* xdrfile;

        xdrfile = xdrfile_open(input.c_str(),"r");
        if (NULL == xdrfile)
            std::cerr << "Error opening file.\n";
        else
            output(xdrfile,atoms,input,output_file);
    }
}